class_name Room
extends Node2D

@export() var enemy_scene: PackedScene

@export() var enermies: Array[Enemy]
@export() var enemy_max_size: int = 10
@export() var soldiers: Array[Soldier]
@export() var gen_enemy_markers: Array[Marker2D]

@export() var win_area: Area2D
@export() var win_area_ui: Label
@export var win_wait_time := 5

var player: Player
var can_win: bool = false
var time_float: float = 0.0
var last_time: float = 0.0

@onready var timer: Timer = %Timer
@onready var win_timer: Timer = %WinTimer
@onready var room_area: Area2D = %RoomArea

func _ready() -> void:
	AutoLoad.add_room(self)
	if timer != null:
		timer.timeout.connect(timeout_cb)
	
	if win_timer:
		win_timer.timeout.connect(win_timeout_cb)
	
	if room_area != null:
		room_area.body_entered.connect(enter_room)
		room_area.body_exited.connect(exit_rooom)
	
	for enemy in enermies:
		enemy.on_die.connect(kill_enemy)
		enemy.set_room(self)
	
	if win_area != null:
		win_area.body_entered.connect(enter_win_area)
		win_area.body_exited.connect(exit_win_area)
	
	for i in enemy_max_size - enermies.size():
		gen_enemy()

func _physics_process(_delta: float) -> void:
	if (need_gen_enemy() && timer != null && timer.is_stopped()):
		timer.start()
	soldiers.clear()
	for i in $RoomArea.get_overlapping_bodies():
		if i is Soldier:
			soldiers.append(i)
	if win_area && AutoLoad.every_room_win():
		can_win = true
		if win_timer and !win_timer.is_stopped():
			last_time = Time.get_unix_time_from_system() - time_float
			if last_time > win_wait_time: last_time = win_wait_time
			win_area_ui.text = String.num(win_wait_time - last_time, 2)
	else:
		can_win = false
		if win_timer: win_timer.stop()

func enter_win_area(body: Node2D) -> void:
	if body is Player and can_win:
		win_timer.start(win_wait_time)
		time_float = Time.get_unix_time_from_system()
		last_time = 0.0

func exit_win_area(body: Node2D) -> void:
	if body is Player:
		# time wait pause
		win_timer.stop()
		last_time = 0.0
		win_area_ui.text = str(win_wait_time)
		pass

func has_soliders() -> bool:
	return soldiers.size() > 0 || player != null

func enter_room(body: Node2D) -> void:
	if body is Player:
		player = body
		player.on_die.connect(kill_player)

func exit_rooom(body: Node2D) -> void:
	if body is Player:
		player.on_die.disconnect(kill_player)
		player = null	

func kill_enemy(enemy: Enemy) -> void:
	if enermies.has(enemy):
		enermies.erase(enemy)

func kill_player() -> void:
	if player != null:
		player = null

func need_gen_enemy() -> bool:
	return (player != null || soldiers.size() > 0) && enermies.size() < enemy_max_size

func gen_enemy() -> void:
	if enemy_scene == null || gen_enemy_markers.size() == 0 || enermies.size() >= enemy_max_size:
		return
	var rand_index := randi_range(0, gen_enemy_markers.size() - 1)
	var marker := gen_enemy_markers[rand_index]
	var enemy := enemy_scene.instantiate() as Enemy
	enemy.set_room(self)
	enemy.on_die.connect(kill_enemy)
	enermies.append(enemy)
	self.add_child(enemy)
	var rand_offset := Vector2(randf_range(-50, 50), randf_range(-50, 50))
	enemy.global_position = marker.global_position + rand_offset

func timeout_cb() -> void:
	if need_gen_enemy():
		gen_enemy()

func win_timeout_cb() -> void:
	if player != null:
		player.win()
		player = null
		timer.stop()
		pass
